home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue42 / diagram / MainForm.pas next >
Encoding:
Pascal/Delphi Source File  |  1999-01-13  |  12.2 KB  |  417 lines

  1. unit MainForm;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  7.   ComCtrls, ToolWin, JimShape, ImgList, ExtCtrls;
  8.  
  9. type
  10.   TjimNextAction = (jnaNone,jnaAddActor,jnaAddUseCase,
  11.                     jnaStartDouble,jnaEndDouble,
  12.                     jnaStartUsesArrow,jnaEndUsesArrow,
  13.                     jnaStartExtendsArrow,jnaEndExtendsArrow);
  14.  
  15.   TjimArrowType = (jatDouble,jatUses,jatExtends);
  16.  
  17.  
  18.   TMainDlg = class(TForm)
  19.     ToolBar1: TToolBar;
  20.     ScrollBox1: TScrollBox;
  21.     NewBtn: TToolButton;
  22.     OpenBtn: TToolButton;
  23.     SaveBtn: TToolButton;
  24.     ToolButton5: TToolButton;
  25.     SelectBtn: TToolButton;
  26.     ActorBtn: TToolButton;
  27.     UseCaseBtn: TToolButton;
  28.     DoubleArrowBtn: TToolButton;
  29.     UsesArrowBtn: TToolButton;
  30.     BtnImageList: TImageList;
  31.     ExtendsArrowBtn: TToolButton;
  32.     OpenDialog1: TOpenDialog;
  33.     SaveDialog1: TSaveDialog;
  34.     DiagImageList: TImageList;
  35.     ToolButton1: TToolButton;
  36.     DeleteBtn: TToolButton;
  37.     StatusBar: TStatusBar;
  38.     procedure NewBtnClick(Sender: TObject);
  39.     procedure OpenBtnClick(Sender: TObject);
  40.     procedure SaveBtnClick(Sender: TObject);
  41.     procedure SelectBtnClick(Sender: TObject);
  42.     procedure ActorBtnClick(Sender: TObject);
  43.     procedure UseCaseBtnClick(Sender: TObject);
  44.     procedure DoubleArrowBtnClick(Sender: TObject);
  45.     procedure UsesArrowBtnClick(Sender: TObject);
  46.     procedure ExtendsArrowBtnClick(Sender: TObject);
  47.     procedure FormCreate(Sender: TObject);
  48.     procedure ScrollBox1MouseDown(Sender: TObject; Button: TMouseButton;
  49.       Shift: TShiftState; X, Y: Integer);
  50.     procedure DeleteBtnClick(Sender: TObject);
  51.   private
  52.     FNextAction : TjimNextAction;
  53.     FStartShape : TjimCustomShape;
  54.     FEndShape   : TjimCustomShape;
  55.  
  56.     procedure SetNextAction(Value : TjimNextAction);
  57.     procedure ChooseButton(TheButton : TToolButton);
  58.     procedure ConnectShapes(StartShape,EndShape : TjimCustomShape;
  59.                             ArrowType : TjimArrowType);
  60.   public
  61.     property NextAction : TjimNextAction read FNextAction write SetNextAction;
  62.   published
  63.     // The OnClick event handler for all shapes on the diagram
  64.     procedure ShapeClick(Sender : TObject);
  65.     // The OnDblClick event handler for all captions on the diagram
  66.     procedure CaptionDblClick(Sender : TObject);
  67.   end;
  68.  
  69.  
  70.   EDiagramError = class(Exception);
  71.  
  72.  
  73. var
  74.   MainDlg: TMainDlg;
  75.  
  76.  
  77. implementation
  78.  
  79. {$R *.DFM}
  80.  
  81. uses
  82.   CaptionEditForm;
  83.  
  84.  
  85. procedure TMainDlg.SetNextAction(Value: TjimNextAction);
  86. begin
  87.   FNextAction := Value;
  88.  
  89.   case FNextAction of
  90.     jnaNone              : StatusBar.Panels[0].Text := 'Waiting';
  91.     jnaAddActor          : StatusBar.Panels[0].Text := 'Place an actor on the diagram';
  92.     jnaAddUseCase        : StatusBar.Panels[0].Text := 'Place a use case on the diagram';
  93.     jnaStartDouble       : StatusBar.Panels[0].Text := 'Choose the actor';
  94.     jnaEndDouble         : StatusBar.Panels[0].Text := 'Choose the use case';
  95.     jnaStartUsesArrow    : StatusBar.Panels[0].Text := 'Choose the first use case';
  96.     jnaEndUsesArrow      : StatusBar.Panels[0].Text := 'Choose the second use case';
  97.     jnaStartExtendsArrow : StatusBar.Panels[0].Text := 'Choose the first use case';
  98.     jnaEndExtendsArrow   : StatusBar.Panels[0].Text := 'Choose the second use case';
  99.   end;
  100. end;
  101.  
  102.  
  103. procedure TMainDlg.ChooseButton(TheButton : TToolButton);
  104.   var
  105.     i : Integer;
  106. begin {ChooseButton}
  107.   with ToolBar1 do begin
  108.     for i := 0 to ButtonCount - 1 do begin
  109.       Buttons[i].Down := (Buttons[i] = TheButton);
  110.     end;
  111.   end;
  112.  
  113.   TheButton.Click;
  114. end;  {ChooseButton}
  115.  
  116.  
  117. procedure TMainDlg.ConnectShapes(StartShape,EndShape : TjimCustomShape;
  118.                                  ArrowType : TjimArrowType);
  119.   var
  120.     TempConnector         : TjimConnector;
  121.     StartSide,EndSide     : TjimConnectionSide;
  122.     StartOffset,EndOffset : Integer;
  123. begin {ConnectShapes}
  124.   TempConnector := nil;
  125.   StartSide     := csRight;
  126.   EndSide       := csLeft;
  127.   StartOffset   := FStartShape.Height div 2;
  128.   EndOffset     := FEndShape.Height div 2;
  129.  
  130.   case ArrowType of
  131.     jatDouble  : begin
  132.       TempConnector := TjimDoubleHeadArrow.Create(Self);
  133.     end;
  134.  
  135.     jatUses,
  136.     jatExtends : begin
  137.       TempConnector := TjimBluntSingleHeadArrow.Create(Self);
  138.       // Change the connection sides to top and bottom
  139.       StartSide     := csBottom;
  140.       EndSide       := csTop;
  141.       StartOffset   := FStartShape.Width div 2;
  142.       EndOffset     := FEndShape.Width div 2;
  143.  
  144.       // Create the caption
  145.       TempConnector.Caption := TjimTextShape.Create(Self);
  146.       TempConnector.Caption.OnDblClick := CaptionDblClick;
  147.  
  148.       if ArrowType = jatUses then begin
  149.         TempConnector.Caption.Text := '<<uses>>';
  150.       end else begin
  151.         TempConnector.Caption.Text := '<<extends>>';
  152.       end;
  153.     end;
  154.   end;
  155.  
  156.   with TempConnector do begin
  157.     // Set the start connection
  158.     StartConn.Side   := StartSide;
  159.     StartConn.Offset := StartOffset;
  160.     StartConn.Shape  := FStartShape;
  161.     // Set the end connection
  162.     EndConn.Side     := EndSide;
  163.     EndConn.Offset   := EndOffset;
  164.     EndConn.Shape    := FEndShape;
  165.     // Ensure the size is correct
  166.     SetBoundingRect;
  167.     // Ensure the new control is visible
  168.     Parent := ScrollBox1;
  169.  
  170.     // Align the caption to near the midpoint of the connector, if necessary
  171.     if Assigned(Caption) then begin
  172.       Caption.SetBounds(GetMidPoint.X + 20,GetMidPoint.Y,Caption.Width,Caption.Height);
  173.     end;
  174.   end;
  175. end;  {ConnectShapes}
  176.  
  177.  
  178. procedure TMainDlg.ShapeClick(Sender : TObject);
  179. begin {ShapeClick}
  180.   if not (Sender is TjimCustomShape) then begin
  181.     Exit;
  182.   end;
  183.  
  184.   case FNextAction of
  185.     jnaStartDouble : begin
  186.       // Check that it is an allowed shape
  187.       if not (Sender is TjimBitmapShape) then begin
  188.         raise EDiagramError.Create('You must join an actor to a use case');
  189.       end;
  190.  
  191.       FStartShape := TjimCustomShape(Sender);
  192.       NextAction  := jnaEndDouble;
  193.     end;
  194.  
  195.     jnaEndDouble : begin
  196.       // Check that it is an allowed shape
  197.       if Sender = FStartShape then begin
  198.         raise EDiagramError.Create('You cannot join an actor to itself, ' +
  199.                                    'choose a use case instead');
  200.       end else if not (Sender is TjimStandardShape) then begin
  201.         raise EDiagramError.Create('You must join an actor to a use case');
  202.       end;
  203.  
  204.       FEndShape := TjimCustomShape(Sender);
  205.       ConnectShapes(FStartShape,FEndShape,jatDouble);
  206.       ChooseButton(SelectBtn);
  207.     end;
  208.  
  209.     jnaStartUsesArrow : begin
  210.       // Check that it is an allowed shape
  211.       if not (Sender is TjimStandardShape) then begin
  212.         raise EDiagramError.Create('You must join a use case to a use case');
  213.       end;
  214.  
  215.       FStartShape := TjimCustomShape(Sender);
  216.       NextAction  := jnaEndUsesArrow;
  217.     end;
  218.  
  219.     jnaEndUsesArrow : begin
  220.       // Check that it is an allowed shape
  221.       if Sender = FStartShape then begin
  222.         raise EDiagramError.Create('You cannot join a use case to itself, ' +
  223.                                    'choose another use case instead');
  224.       end else if not (Sender is TjimStandardShape) then begin
  225.         raise EDiagramError.Create('You must join a use case to a use case');
  226.       end;
  227.  
  228.       FEndShape := TjimCustomShape(Sender);
  229.       ConnectShapes(FStartShape,FEndShape,jatUses);
  230.       ChooseButton(SelectBtn);
  231.     end;
  232.  
  233.     jnaStartExtendsArrow : begin
  234.       // Check that it is an allowed shape
  235.       if not (Sender is TjimStandardShape) then begin
  236.         raise EDiagramError.Create('You must join a use case to a use case');
  237.       end;
  238.  
  239.       FStartShape := TjimCustomShape(Sender);
  240.       NextAction  := jnaEndExtendsArrow;
  241.     end;
  242.  
  243.     jnaEndExtendsArrow : begin
  244.       // Check that it is an allowed shape
  245.       if Sender = FStartShape then begin
  246.         raise EDiagramError.Create('You cannot join a use case to itself, ' +
  247.                                    'choose another use case instead');
  248.       end else if not (Sender is TjimStandardShape) then begin
  249.         raise EDiagramError.Create('You must join a use case to a use case');
  250.       end;
  251.  
  252.       FEndShape := TjimCustomShape(Sender);
  253.       ConnectShapes(FStartShape,FEndShape,jatExtends);
  254.       ChooseButton(SelectBtn);
  255.     end;
  256.   end;
  257. end;  {ShapeClick}
  258.  
  259.  
  260. procedure TMainDlg.CaptionDblClick(Sender : TObject);
  261.   var
  262.     TempText : string;
  263.     TempFont : TFont;
  264. begin {CaptionDblClick}
  265.   if Sender is TjimTextShape then begin
  266.     with TjimTextShape(Sender) do begin
  267.       // Use local variables because cannot pass properties as var parameters
  268.       TempText := Text;
  269.       TempFont := Font;
  270.       TCaptionEditDlg.NewCaption(TempText,TempFont);
  271.       Text := TempText;
  272.       Font := TempFont;
  273.     end;
  274.   end;
  275. end;  {CaptionDblClick}
  276.  
  277.  
  278. procedure TMainDlg.FormCreate(Sender: TObject);
  279. begin
  280.   NextAction  := jnaNone;
  281.   FStartShape := nil;
  282.   FEndShape   := nil;
  283. end;
  284.  
  285.  
  286. procedure TMainDlg.NewBtnClick(Sender: TObject);
  287. begin
  288.   TjimCustomShape.DeleteAllShapes(ScrollBox1);
  289. end;
  290.  
  291.  
  292. procedure TMainDlg.OpenBtnClick(Sender: TObject);
  293. begin
  294.   if OpenDialog1.Execute then begin
  295.     TjimCustomShape.LoadFromFile(OpenDialog1.FileName,ScrollBox1);
  296.   end;
  297. end;
  298.  
  299.  
  300. procedure TMainDlg.SaveBtnClick(Sender: TObject);
  301. begin
  302.   if SaveDialog1.Execute then begin
  303.     TjimCustomShape.SaveToFile(SaveDialog1.FileName,ScrollBox1);
  304.   end;
  305. end;
  306.  
  307.  
  308. procedure TMainDlg.SelectBtnClick(Sender: TObject);
  309. begin
  310.   // Don't add anything to the diagram on the next click on the scrollbox
  311.   NextAction  := jnaNone;
  312. end;
  313.  
  314.  
  315. procedure TMainDlg.ActorBtnClick(Sender: TObject);
  316. begin
  317.   // Add an actor to the diagram on the next click on the scrollbox
  318.   NextAction  := jnaAddActor;
  319. end;
  320.  
  321.  
  322. procedure TMainDlg.UseCaseBtnClick(Sender: TObject);
  323. begin
  324.   // Add a use case to the diagram on the next click on the scrollbox
  325.   NextAction  := jnaAddUseCase;
  326. end;
  327.  
  328.  
  329. procedure TMainDlg.DoubleArrowBtnClick(Sender: TObject);
  330. begin
  331.   // Connect an actor to a use case
  332.   NextAction  := jnaStartDouble;
  333.   FStartShape := nil;
  334.   FEndShape   := nil;
  335. end;
  336.  
  337.  
  338. procedure TMainDlg.UsesArrowBtnClick(Sender: TObject);
  339. begin
  340.   // Connect 2 use cases
  341.   NextAction  := jnaStartUsesArrow;
  342.   FStartShape := nil;
  343.   FEndShape   := nil;
  344. end;
  345.  
  346.  
  347. procedure TMainDlg.ExtendsArrowBtnClick(Sender: TObject);
  348. begin
  349.   // Connect 2 use cases
  350.   NextAction  := jnaStartExtendsArrow;
  351.   FStartShape := nil;
  352.   FEndShape   := nil;
  353. end;
  354.  
  355.  
  356. procedure TMainDlg.DeleteBtnClick(Sender: TObject);
  357. begin
  358.   TjimCustomShape.DeleteSelectedShapes(ScrollBox1);
  359. end;
  360.  
  361.  
  362. procedure TMainDlg.ScrollBox1MouseDown(Sender : TObject;Button : TMouseButton;
  363.                                        Shift : TShiftState;X,Y : Integer);
  364. begin
  365.   case FNextAction of
  366.     jnaNone : TjimCustomShape.UnselectAllShapes(ScrollBox1);
  367.  
  368.     jnaAddActor : begin
  369.       with TjimBitmapShape.Create(Self) do begin
  370.         Caption            := TjimTextShape.Create(Self);
  371.         Caption.Text       := 'New Actor';
  372.         Caption.OnDblClick := CaptionDblClick;
  373.         Images             := DiagImageList;
  374.         ImageIndex         := 0;
  375.         Top                := Y;
  376.         Left               := X;
  377.         OnClick            := ShapeClick;
  378.         Parent             := ScrollBox1;
  379.         AlignCaption(taCenter);
  380.       end;
  381.  
  382.       ChooseButton(SelectBtn);
  383.     end;
  384.  
  385.     jnaAddUseCase : begin
  386.       with TjimStandardShape.Create(Self) do begin
  387.         Caption            := TjimTextShape.Create(Self);
  388.         Caption.Text       := 'New Use Case';
  389.         Caption.OnDblClick := CaptionDblClick;
  390.         ShapeType          := stEllipse;
  391.         Top                := Y;
  392.         Left               := X;
  393.         OnClick            := ShapeClick;
  394.         Parent             := ScrollBox1;
  395.         AlignCaption(taCenter);
  396.         Caption.Top := Top + (Height div 2) - (Caption.Height div 2);
  397.       end;
  398.  
  399.       ChooseButton(SelectBtn);
  400.     end;
  401.  
  402.     jnaStartDouble,
  403.     jnaEndDouble,
  404.     jnaStartUsesArrow,
  405.     jnaEndUsesArrow,
  406.     jnaStartExtendsArrow,
  407.     jnaEndExtendsArrow : begin
  408.       // Shouldn't really get here when doing anything useful, so treat it as
  409.       // clearing the setting
  410.       ChooseButton(SelectBtn);
  411.     end;
  412.   end;
  413. end;
  414.  
  415.  
  416. end.
  417.